#include "tcpclient.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <mutex>
#include <unistd.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 12345
#define THREAD_NUM 10
#define SEND_COUNT 5
#define MIN_NUM 100
#define MAX_NUM MIN_NUM * 10
#define BUF_LENGTH MAX_NUM + 1

std::mutex gMutex;
int gIndex = 0;
long num1[THREAD_NUM], num2[THREAD_NUM];
const char* pstr = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

void* threadCallback(void* arg) {
    int strlength = strlen(pstr);
    int n = 0;
    long length = 0, count = 0;
    {
        std::unique_lock<std::mutex> lock(gMutex);
        n = gIndex++;
        length = num1[n];
        count = num2[n];
    }

    TcpClient tc;
    int ret = tc.connect(SERVER_IP, SERVER_PORT, 3000);
    if (TCP_CLIENT_E_OK != ret) {
        printf("* connect error : %s(%d)\n", TcpClient::get_errstr(ret), errno);
        return 0;
    }
    
    printf("%d begin, count : %d, length : %d\n", n, count, length);
    char *sbuf = new char[BUF_LENGTH], *rbuf = new char[BUF_LENGTH];
    int number = count;
    while (count--) {
        memset(sbuf, 0, sizeof(sbuf));
        for (int i = 0; i < length; i++) {
            sbuf[i] = pstr[rand()%strlength];
        }
        ret = tc.send(sbuf, length, 3000);
        if (TCP_CLIENT_E_OK != ret) {
            printf("* send error : %s(%d)\n", TcpClient::get_errstr(ret), errno);
            break;
        }

        memset(rbuf, 0, sizeof(rbuf));
        ret = tc.recv(rbuf, length, 3000);
        if (TCP_CLIENT_E_OK != ret) {
            printf("* recv error : %s(%d)\n", TcpClient::get_errstr(ret), errno);
            break;
        }

        if (strcmp(sbuf, rbuf) != 0) {
            printf("* data error\n");
        } else {
            //printf("data ok\n");
        }
    }
    printf("%d end, count : %d, length : %d\n", n, number, length);

    delete [] sbuf;
    delete [] rbuf;
    //sleep(1000);
    return 0;
}

int main() {
    srand(time(0));
    for (int i = 0; i < THREAD_NUM; i++) {
        int r = rand()%MAX_NUM;
        num1[i] = r < MIN_NUM ? MIN_NUM : r;
        num2[i] = rand() % SEND_COUNT + 1;
    }
    std::vector<pthread_t> p_threads;
    for (int i = 0; i < THREAD_NUM; i++) {
        pthread_t pt = 0;
        if (pthread_create(&pt, NULL, threadCallback, NULL)) {
            printf("pthread_create error %d", errno);
            return -1;
        }
        p_threads.push_back(pt);
    }
    for (int i = 0; i < THREAD_NUM; i++) {
        pthread_join(p_threads[i], NULL);
    }
    p_threads.clear();
    return 0;
}
